﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Phoenix.Xna.Framework.Properties;

namespace Phoenix.Xna.Framework.Graphics
{
    public abstract class Shader<T> : EngineComponent, IShader<T>
    {
        private string _asset;

        public Shader(string asset, bool isEffectMap)
            : base()
        {
            InitailizeEffect(asset, isEffectMap);
        }

        public Shader(EffectMap effectMap)
            : base()
        {
            EffectMap = effectMap;
        }

        public Shader(string id, string asset, bool isEffectMap)
            : base(id)
        {
            InitailizeEffect(asset, isEffectMap);
        }

        public Shader(string id, EffectMap effectMap)
            : base(id)
        {
            EffectMap = effectMap;
        }

        protected void Dispose(bool disposing)
        {
            if (!IsDisposed && disposing)
            {
                EffectMap.Dispose();
            }

            IsDisposed = true;
        }

        private void InitailizeEffect(string asset, bool isEffectMap)
        {
            if (string.IsNullOrEmpty(asset))
            {
                throw new ArgumentNullException(string.Format(Resources.ArgumentNullException, "asset"));
            }

            _asset = asset;

            if (isEffectMap)
            {
                EffectMap = Engine.Instance.Content.Load<EffectMap>(asset);
            }
            else
            {
                EffectMap = new EffectMap();
                EffectMap.SetEffect(asset);
                EffectMap.LoadContent();
            }
        }

        #region IShader Members

        public abstract void Draw(GameTime gameTime, T state);

        #endregion

        #region IImplementsEffectMap Members

        public virtual EffectMap EffectMap { get; set; }

        public virtual void LoadEffectMap(string effectMap)
        {
            if (string.IsNullOrEmpty(effectMap))
            {
                throw new ArgumentNullException(string.Format(Resources.ArgumentNullException, "effectMap"));
            }

            EffectMap = Engine.Instance.Content.Load<EffectMap>(effectMap);
        }

        #endregion

        #region IDisposableEx Members

        public bool IsDisposed { get; private set; }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}
